home *** CD-ROM | disk | FTP | other *** search
- /********************************************************/
- /* UserObj Module for SkyView */
- /* */
- /* (c)1992 N P Hawkes */
- /* */
- /* Displays User Object at specified RA & Dec */
- /********************************************************/
-
- #include "menu.h"
- #include "dbox.h"
- #include "bbc.h"
- #include "wimpt.h"
- #include "dbox.h"
- #include "string.h"
- #include "event.h"
- #include "res.h"
- #include "resspr.h"
- #include "werr.h"
- #include "os.h"
-
- #include "sv_header.h"
- #include "userobj.h"
- #include "radec.h"
-
- #include <stdio.h>
- #include <stdlib.h>
-
- /********************************************************/
- /* Constants */
- /********************************************************/
- #define DISP_NAME ">User obj." /*Entry in Display menu.*/
- #define SEL_NAME " User obj." /*Entry in Select menu. */
- #define FILE_NAME "UserData" /* Name of disc file. */
- #define DISPBOX_NAME "UserDisp" /* Name of Disp dbox. */
- #define SPRITE_NAME "userobj" /*Name of UserObj Sprite*/
-
- #define HORALT (REAL)0.0044 /* Altitude of horizon.*/
-
- /* Length of one line of description (inc. \0 at end): */
- #define USEROBJ_TEXTLEN 31
-
- /* Constants relating to Display dialogue box. */
- enum {
- box_destroy = -1, /* Response cancelling the dbox. */
- ok_butt = 0, /* OK button. */
- cancel_butt, /* Cancel button. */
- show_butt, /* Show Defaults button. */
- set_butt, /* Set Defaults button. */
- rah_field, /* Field for hour part of RA. */
- ram_field, /* Field for minute part of RA. */
- decd_field, /* Field for degree part of Dec. */
- decm_field, /* Field for minute part of Dec. */
- ns_field, /* Field for 'N' or 'S'. */
- ns_butt, /* Button to toggle between N & S. */
- rah_tu = 10, /* Increment tens in rah_field. */
- rah_td, /* Decrement tens in rah_field. */
- rah_uu, /* Increment units in rah_field. */
- rah_ud, /* Decrement units in rah_field. */
- ram_tu = 14, /* Increment tens in ram_field. */
- ram_td, /* Decrement tens in ram_field. */
- ram_uu, /* Increment units in ram_field. */
- ram_ud, /* Decrement units in ram_field. */
- decd_tu = 18, /* Increment tens in decd_field. */
- decd_td, /* Decrement tens in decd_field. */
- decd_uu, /* Increment units in decd_field. */
- decd_ud, /* Decrement units in decd_field. */
- decm_tu = 22, /* Increment tens in decm_field. */
- decm_td, /* Decrement tens in decm_field. */
- decm_uu, /* Increment units in decm_field. */
- decm_ud, /* Decrement units in decm_field. */
- text1_field = 26, /* Field for first line of text. */
- text2_field, /* Field for 2nd line of text. */
- text3_field /* Field for 3rd line of text. */
- };
-
- /********************************************************/
- /* New types of variable. */
- /********************************************************/
- /* Structure describing data on show in Display dbox. */
- typedef struct {
- int rah; /* Hour part of Right Ascension. */
- int ram; /* Minute part of Right Ascension. */
- int decd; /* Degree part of Declination. */
- int decm; /* Minute part of Declination. */
- BOOL isn; /* TRUE if Dec is North. */
- char text1[USEROBJ_TEXTLEN]; /* First line of text. */
- char text2[USEROBJ_TEXTLEN]; /* 2nd line of text. */
- char text3[USEROBJ_TEXTLEN]; /* 3rd line of text. */
- } userobjstr;
-
- /********************************************************/
- /* Global Variables */
- /********************************************************/
- static BOOL display_flag = FALSE; /* 'Enabled' flag. */
- /* Flag indicating whether a Rebuild Request is pending:*/
- static BOOL request_pending = FALSE;
- static int moduleid; /* Module ID. */
- static sprite_id spr_id; /* For Userobj sprite*/
-
- static dbox d_disp; /* Display dbox. */
- static userobjstr current_data = { /* Current data. */
- 0,
- 0,
- 0,
- 0,
- TRUE,
- "",
- "<Untitled>",
- ""
- };
-
- static REAL ra; /* Current RA. */
- static REAL dec; /* Current Dec. */
-
- static int horiz_id; /* Current ID in Horiz window. */
- static int vert_id; /* Current ID in Vert window. */
-
- static int addon[4] = /* For incrementing / decrement-*/
- { 10, /* ing numbers in Display dbox. */
- -10,
- 1,
- -1 };
-
- /********************************************************/
- /* Function Prototypes */
- /********************************************************/
- static BOOL read_discfile(userobjstr *ptr);
- static void userobj_radec(userobjstr *ptr, REAL *raptr, REAL *decptr);
- static BOOL write_discfile(userobjstr *ptr);
- static void userobj_buildfn(void);
- static BOOL userobj_displayfn(BOOL *enabptr);
- static void load_dispbox(userobjstr *ptr);
- static void read_dispbox(userobjstr *ptr);
- static BOOL dispbox_buttons(void);
- static BOOL copy_data(userobjstr *ptr1, userobjstr *ptr2);
- static void dispbox_databutts(int response);
- static os_error *userobj_plotfn(int x, int y, int id);
- static void userobj_infofn(int id);
- static void userobj_selectfn(selectfn_reasoncode reason);
- static void selection_details(void);
-
- /********************************************************/
- /* Initialisation Function */
- /********************************************************/
- BOOL userobj_initfn(int moduleno, modulestr *userobj)
- {
- sprite_id nametype_id;
- os_error *errptr;
-
- /* Record the module number of this module. */
- moduleid = moduleno;
-
- /* Attempt to read default settings from disc. If */
- /* error, just carry on with hard-wired settings. */
- read_discfile(¤t_data);
- /* Set the RA and Dec to correspond with these values. */
- userobj_radec(¤t_data, &ra, &dec);
-
- /* Initialise sprite identifier. */
- /* First build a name-type sprite id. */
- nametype_id.s.name = SPRITE_NAME;
- nametype_id.tag = sprite_id_name;
- /* Then get the sprite's address & put it in the global */
- /* sprite identifier spr_id. */
- errptr = sprite_select_rp(resspr_area(), &nametype_id, &spr_id.s.addr);
- if (errptr != NULL) return FALSE;
- /* Finally tag the identifier spr_id as address-type. */
- spr_id.tag = sprite_id_addr;
-
- /* Fill in the fields of the modulestr. */
- userobj->buildfn = userobj_buildfn;
- userobj->selectfn = userobj_selectfn;
- userobj->dispfn = userobj_displayfn;
- userobj->infofn = userobj_infofn;
- userobj->initial = display_flag;
- userobj->display_entry = DISP_NAME;
- userobj->display_menu = NULL;
- userobj->select_entry = SEL_NAME;
- userobj->select_menu = NULL;
-
- return TRUE;
- }
-
- /*------------------------------------------------------*/
- /* Function to read default values of RA, Dec and text */
- /* from disc file. Returns TRUE if data read OK. If */
- /* error, returns FALSE and leaves *ptr unchanged. */
- /*------------------------------------------------------*/
- static BOOL read_discfile(userobjstr *ptr)
- {
- userobjstr tempstr[1];
- FILE *fileptr;
- size_t numread;
-
- /* Open disc file for reading binary. */
- fileptr = res_openfile(FILE_NAME, "rb");
- if (fileptr == NULL) return FALSE;
-
- /* Try to read one userobjstr from file. */
- numread = fread((void *)tempstr, sizeof(userobjstr), 1, fileptr);
-
- /* Close disc file. Fatal error if it won't close. */
- if (fclose(fileptr) != 0)
- werr(FATAL, "UserObj Error: Can't close Default file");
-
- /* If attempt to read failed, return FALSE now. */
- if (numread != 1) return FALSE;
-
- /* All OK, so transfer data to *ptr and return TRUE. */
- *ptr = tempstr[0];
- return TRUE;
- }
-
- /*------------------------------------------------------*/
- /* Function to write to disc the values of RA, Dec and */
- /* text pointed to by ptr. Returns FALSE if error. */
- /*------------------------------------------------------*/
- static BOOL write_discfile(userobjstr *ptr)
- {
- userobjstr tempstr[1];
- FILE *fileptr;
- size_t numwritten;
-
- /* Copy data into array variable. */
- tempstr[0] = *ptr;
-
- /* Open disc file for writing binary. */
- fileptr = res_openfile(FILE_NAME, "wb");
- if (fileptr == NULL) return FALSE;
-
- /* Try to write one userobjstr to file. */
- numwritten = fwrite((void *)tempstr, sizeof(userobjstr), 1, fileptr);
-
- /* Close disc file. Fatal error if it won't close. */
- if (fclose(fileptr) != 0)
- werr(FATAL, "UserObj Error: Can't close Default file");
-
- /* Return sucess or failure. */
- return (numwritten == 1);
- }
-
- /*------------------------------------------------------*/
- /* Function to calculate the RA and Dec from the data */
- /* pointed to by ptr. */
- /*------------------------------------------------------*/
- static void userobj_radec(userobjstr *ptr, REAL *raptr, REAL *decptr)
- {
- REAL hours, degrees;
-
- hours = (REAL)(ptr->rah) + (REAL)(ptr->ram) / (REAL)60.0;
- degrees = (REAL)(ptr->decd) + (REAL)(ptr->decm) / (REAL)60.0;
-
- *raptr = CONV * (REAL)15.0 * hours;
- if (*raptr >= TWO_PI) *raptr = ZERO;
-
- *decptr = CONV * degrees;
- if (!ptr->isn) *decptr = -(*decptr);
- if (*decptr > PIby2) *decptr = PIby2;
- if (*decptr < -PIby2) *decptr = -PIby2;
-
- return;
- }
-
- /********************************************************/
- /* List-Building Function */
- /********************************************************/
- static void userobj_buildfn(void)
- {
- plotobj userobj;
-
- /* Bounding box of plotting symbol, relative to */
- /* position of symbol: */
- static wimp_box size = {-12, -12, 14, 14};
-
- /* Choose to keep plotting list up-to-date with all */
- /* changes in Observer details, so omit check on */
- /* whether module is enabled or not. */
-
- /* Any pending rebuild request is now being met. */
- request_pending = FALSE;
-
- /*Build plotobj for the one object owned by this module.*/
- userobj.id = 0;
- userobj.module = moduleid;
- userobj.plotfn = userobj_plotfn;
- radec_altaz(ra, dec, &ob_data, ob_data.sid, &userobj.alt, &userobj.azim);
- userobj.size = size;
-
- /* Offer this to the main program. */
- addobj(userobj, &horiz_id, &vert_id);
-
- return;
- }
-
-
- /********************************************************/
- /* Object-Selecting Function */
- /********************************************************/
- static void userobj_selectfn(selectfn_reasoncode reason)
- {
-
- switch (reason)
- {
- case new_selection:
- /* Only one User Object, so selection always */
- /* succeeds. */
- selection.id = 0;
- selection.selected_OK = TRUE;
- case window_selection:
- /* A selection has been made by clicking in a */
- /* window. */
- case recalculate_data:
- /* Observer details have changed, and plotting */
- /* lists have been rebuilt. */
- /* */
- /* Fill in details of rising, setting etc. */
- selection_details();
- break;
-
- case timeonly_recalculate:
- /* As recalculate_data, but only the time of day */
- /* (and possibly the direction of view - this is */
- /* is of no interest) have changed. */
- /* This simplifies the calculation. */
- selection.horiz_id = horiz_id;
- selection.vert_id = vert_id;
- /* Decide if it can be seen now. */
- selection.now = selection.horiz_id != NOWHERE || \
- selection.vert_id != NOWHERE;
- break;
-
- case sel_info_request:
- /* Write info into text buffer. Use Info fn. */
- userobj_infofn(0);
- break;
-
- default:
- /* Unknown option. Do nothing. */
- break;
-
- }
-
- return;
- }
-
- /*------------------------------------------------------*/
- /* Function to fill in selection details of selected */
- /* User Object (viewing directions and times for rising,*/
- /* setting, culminating etc). */
- /*------------------------------------------------------*/
- static void selection_details(void)
- {
- double ch; /* cos of hour angle at horizon. */
- BOOL riset; /* Whether object rises & sets or not. */
- BOOL culmin; /* Whether object culminates or not. */
-
- /* Record window IDs of User Object. */
- selection.horiz_id = horiz_id;
- selection.vert_id = vert_id;
-
- /* Find out if it can be seen now. */
- selection.now = selection.horiz_id != NOWHERE || \
- selection.vert_id != NOWHERE;
-
- /* Find out if Object rises, sets or culminates today. */
- /* (After setting effective altitude of horizon.) */
- radec_sethoriz(HORALT);
-
- radec_phenomena(ra, dec, &ob_data, &ch, &riset, &culmin);
- selection.rising = riset;
- selection.setting = riset;
- selection.culminating = culmin;
-
- /* Fill in details for each phenomenon which occurs. */
-
- if (selection.rising)
- radec_rise_details(ra, dec, &ob_data, ch,
- &selection.rise_azim,
- &selection.rise_hour,
- &selection.rise_min);
-
- if (selection.setting)
- radec_set_details(ra, dec, &ob_data, ch,
- &selection.set_azim,
- &selection.set_hour,
- &selection.set_min);
-
- if (selection.culminating)
- radec_cul_details(ra, dec, &ob_data,
- &selection.cul_alt,
- &selection.cul_azim,
- &selection.cul_hour,
- &selection.cul_min);
-
- return;
- }
-
- /********************************************************/
- /* Display Function */
- /********************************************************/
- static BOOL userobj_displayfn(BOOL *enabptr)
- {
- BOOL changes;
-
- /* Respond to click on Display menu entry, or to move- */
- /* ment of pointer over arrow on menu entry. */
-
- /* Find out whether or not event was a menu choice. */
- if (wimpt_last_event()->e == wimp_EMENU)
- {
- /* Menu choice. */
- /* Toggle Enable/Disable flag. */
- display_flag = !display_flag;
-
- /* Inform main program of new status. */
- *enabptr = display_flag;
-
- /* Issue a Rebuild Request if one is pending. */
- rebuild_request = request_pending;
-
- /* Windows will always need updating. */
- return TRUE;
- }
-
- /* User has invoked Display dialogue box. */
- /* Create dialogue box, load it with data, and put it */
- /* on display (if not already done). */
- if (!dbox_persisting)
- {
- d_disp = dbox_new(DISPBOX_NAME);
- if (d_disp == NULL) return FALSE;
- load_dispbox(¤t_data);
- dbox_show(d_disp);
- }
-
- /* Deal with clicks on buttons until action by main */
- /* program is required. Fn returns TRUE if changes */
- /* affecting the appearance of the windows have been */
- /* made. */
- changes = dispbox_buttons();
-
- /* Delete disp box if it is not required to persist. */
- if (!dbox_persisting) dbox_dispose(&d_disp);
-
- /* Plotting lists will need rebuilding if significant */
- /* changes have been made. */
- /* If module is currently enabled, issue request now. */
- /* If not, make a note that a request is pending. */
- rebuild_request = (changes || request_pending) && display_flag;
- request_pending = (changes || request_pending) && !display_flag;
-
- /* Windows will need updating if and only if plotting */
- /* lists need rebuilding. */
- return rebuild_request;
- }
-
- /*------------------------------------------------------*/
- /* Function to load dbox with data pointed to by ptr. */
- /*------------------------------------------------------*/
- static void load_dispbox(userobjstr *ptr)
- {
- char numbuf[16];
-
- /* Right Ascension (hour part, then minute part): */
- sprintf(numbuf, "%02.2i", ptr->rah);
- dbox_setfield(d_disp, rah_field, numbuf);
- sprintf(numbuf, "%02.2i", ptr->ram);
- dbox_setfield(d_disp, ram_field, numbuf);
-
- /* Declination (degrees, then minutes, then North/South)*/
- sprintf(numbuf, "%02.2i", ptr->decd);
- dbox_setfield(d_disp, decd_field, numbuf);
- sprintf(numbuf, "%02.2i", ptr->decm);
- dbox_setfield(d_disp, decm_field, numbuf);
- dbox_setfield(d_disp, ns_field, (ptr->isn ? "N" : "S"));
-
- /* Three lines of text: */
- dbox_setfield(d_disp, text1_field, ptr->text1);
- dbox_setfield(d_disp, text2_field, ptr->text2);
- dbox_setfield(d_disp, text3_field, ptr->text3);
-
- return;
- }
-
- /*------------------------------------------------------*/
- /* Function to read the data in the Display dbox, and */
- /* copy them to the userobjstr pointed to by ptr. */
- /*------------------------------------------------------*/
- static void read_dispbox(userobjstr *ptr)
- {
- char nsbuf[2];
-
- /* Right Ascension (hour part, then minute part): */
- ptr->rah = dbox_getnumeric(d_disp, rah_field);
- ptr->ram = dbox_getnumeric(d_disp, ram_field);
-
- /* Declination (degrees, minutes, North / South): */
- ptr->decd = dbox_getnumeric(d_disp, decd_field);
- ptr->decm = dbox_getnumeric(d_disp, decm_field);
- dbox_getfield(d_disp, ns_field, nsbuf, 2);
- ptr->isn = (nsbuf[0] == 'N');
-
- /* Three lines of text: */
- dbox_getfield(d_disp, text1_field, ptr->text1, USEROBJ_TEXTLEN);
- dbox_getfield(d_disp, text2_field, ptr->text2, USEROBJ_TEXTLEN);
- dbox_getfield(d_disp, text3_field, ptr->text3, USEROBJ_TEXTLEN);
-
- return;
- }
-
- /*------------------------------------------------------*/
- /* Function to handle clicks on buttons in Display dbox.*/
- /* Returns TRUE if changes have been made which require */
- /* the re-drawing of the windows. */
- /*------------------------------------------------------*/
- static BOOL dispbox_buttons(void)
- {
- int response; /* Button No. clicked by user. */
- BOOL changes; /* TRUE if significant changes.*/
- userobjstr temp_data; /* Temp store for dbox data. */
-
- /* Loop until user clicks on OK, or on Cancel with left */
- /* hand mouse button, or destroys dbox by (eg) clicking */
- /* outside it. */
-
- while (TRUE)
- {
-
- /* Get button number of latest click. */
- response = dbox_fillin(d_disp);
-
- /* Take appropriate action. */
- switch (response) {
-
- case box_destroy:
- /* Box destroyed. Close it & return. */
- dbox_persisting = FALSE;
- return FALSE;
-
- case ok_butt:
- /* Read data in dbox. */
- read_dispbox(&temp_data);
- /* Copy to current_data, noting whether there have*/
- /* been any changes requiring the re-drawing of */
- /* the windows. */
- changes = copy_data(&temp_data, ¤t_data);
- dbox_persisting = dbox_persist();
- /* Can safely ignore clicks with Adjust when no */
- /* significant changes have been made. */
- if (dbox_persisting && !changes) break;
- /* Calc new RA and Dec, if necessary. */
- if (changes) userobj_radec(¤t_data, &ra, &dec);
- return changes;
-
- case cancel_butt:
- /* If click was with Select, close dbox & return. */
- if (!dbox_persist())
- { dbox_persisting = FALSE;
- return FALSE; }
- /* If Adjust, reload current data and continue */
- /* looping. */
- load_dispbox(¤t_data);
- break;
-
- case show_butt:
- /* Load default settings from disc. If error, */
- /* report it and continue; else display new values*/
- if (!read_discfile(&temp_data))
- werr(NON_FATAL, "Can't load defaults");
- else
- load_dispbox(&temp_data);
- break;
-
- case set_butt:
- /* Save dbox settings to disc. If error, report */
- /* it & continue looping. */
- read_dispbox(&temp_data);
- if (!write_discfile(&temp_data))
- { werr(NON_FATAL, "Can't set defaults");
- break; }
- /* If click was with Select, close dbox and */
- /* return (no need to re-draw windows). If Adjust,*/
- /* continue looping. */
- if (!dbox_persist())
- { dbox_persisting = FALSE;
- return FALSE; }
- break;
-
- default:
- /* One of the data-changing buttons. */
- dispbox_databutts(response);
- break;
-
- }
- }
- }
-
- /*------------------------------------------------------*/
- /* Function to handle clicks on the data-changing */
- /* buttons in the Display dialogue box. */
- /*------------------------------------------------------*/
- static void dispbox_databutts(int response)
- {
- char numbuf[16];
- char ns_buf[2];
- int hours, minutes, degrees;
-
- switch (response) {
-
- case rah_tu: case rah_td: case rah_uu: case rah_ud:
- /* Change Hour part of Right Ascension. */
- hours = dbox_getnumeric(d_disp, rah_field);
- hours += addon[response - rah_tu];
- if (hours >= 0 && hours < 24)
- {
- sprintf(numbuf, "%02.2i", hours);
- dbox_setfield(d_disp, rah_field, numbuf);
- }
- break;
-
- case ram_tu: case ram_td: case ram_uu: case ram_ud:
- /* Change Minute part of Right Ascension. */
- minutes = dbox_getnumeric(d_disp, ram_field);
- minutes += addon[response - ram_tu];
- if (minutes >= 0 && minutes < 60)
- {
- sprintf(numbuf, "%02.2i", minutes);
- dbox_setfield(d_disp, ram_field, numbuf);
- }
- break;
-
- case decd_tu: case decd_td: case decd_uu: case decd_ud:
- /* Change Degree part of Declination. */
- degrees = dbox_getnumeric(d_disp, decd_field);
- degrees += addon[response - decd_tu];
- minutes = dbox_getnumeric(d_disp, decm_field);
- if ((degrees >= 0 && degrees < 90) ||
- (degrees == 90 && minutes == 0))
- {
- sprintf(numbuf, "%02.2i", degrees);
- dbox_setfield(d_disp, decd_field, numbuf);
- }
- break;
-
- case decm_tu: case decm_td: case decm_uu: case decm_ud:
- /* Change Minute part of Declination. */
- minutes = dbox_getnumeric(d_disp, decm_field);
- minutes += addon[response - decm_tu];
- if (minutes >= 0 && minutes < 60)
- {
- sprintf(numbuf, "%02.2i", minutes);
- dbox_setfield(d_disp, decm_field, numbuf);
- }
- break;
-
- case ns_butt: case ns_field:
- /* Toggle North / South setting. */
- dbox_getfield(d_disp, ns_field, ns_buf, 2);
- ns_buf[0] = (ns_buf[0] == 'N' ? 'S' : 'N' );
- dbox_setfield(d_disp, ns_field, ns_buf);
- break;
-
- default:
- /* Unknown response. Do nothing. */
- break;
-
- }
- return;
- }
-
- /*------------------------------------------------------*/
- /* Function to check whether two userobjstrs differ */
- /* significantly (ie in a way which would require the */
- /* windows to be re-drawn) and then copy the contents */
- /* of one into the other. */
- /*------------------------------------------------------*/
- static BOOL copy_data(userobjstr *ptr1, userobjstr *ptr2)
- {
- BOOL changes;
-
- changes = ptr1->rah != ptr2->rah ||
- ptr1->ram != ptr2->ram ||
- ptr1->decd != ptr2->decd ||
- ptr1->decm != ptr2->decm ||
- ( ptr1->isn && !ptr2->isn) ||
- (!ptr1->isn && ptr2->isn);
-
- *ptr2 = *ptr1;
-
- return changes;
- }
-
-
- /********************************************************/
- /* Plotting Function */
- /********************************************************/
- static os_error *userobj_plotfn(int x, int y, int id)
- {
- return sv_plotsprite(&spr_id, MODE_20, x, y, 5, 5);
- }
-
-
- /********************************************************/
- /* Info Function */
- /********************************************************/
- static void userobj_infofn(int id)
- {
- sprintf(infoptr,
- "User Object\nRA %02ih %02im Dec %02i° %02i' %c\n%s\n%s\n%s",
- current_data.rah,
- current_data.ram,
- current_data.decd,
- current_data.decm,
- (current_data.isn ? 'N' : 'S'),
- current_data.text1,
- current_data.text2,
- current_data.text3);
-
- return;
- }
-